﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;

using RaisingStudio.Data.Entities;
using RaisingStudio.Data.Common;
using System.Linq.Expressions;
using RaisingStudio.Data.Linq;
using System.Diagnostics;
using System.Data.Common;
using System.Data;

using TestLibrary;
using System.Configuration;

namespace RaisingStudio.Data.TestProject
{
    [TestClass]
    public class UnitTest1
    {
        private DataContext dc;

        public UnitTest1()
        {
			IDbConnection connection = null;
			string providerName = null;
			// string settingName =  "RaisingStudio.Data.TestProject.Properties.Settings.DefaultConnectionString";
			string settingName =  "RaisingStudio.Data.TestProject.Properties.Settings.MySqlConnectionString";
			//this.dc = new DataContext("RaisingStudio.Data.TestProject.Properties.Settings.SqliteConnectionString");
            //this.dc = new DataContext("RaisingStudio.Data.TestProject.Properties.Settings.OracleConnectionString");
			ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[settingName];
            if (connectionStringSettings != null)
            {
				switch(connectionStringSettings.ProviderName)
				{
					case "MySql.Data.MySqlClient":
					{
                		connection = new MySql.Data.MySqlClient.MySqlConnection(connectionStringSettings.ConnectionString);                
						providerName = connectionStringSettings.ProviderName;
						break;
					}
				}
            }
            this.dc = new DataContext(connection, providerName);
            this.dc.Log = Console.Out;
        }

        [TestMethod]
        public void TestMethod1()
        {
            Assert.IsTrue(true);
        }

        [TestMethod]
        public void Test2()
        {
            Assert.IsNotNull(new DataContext());
            //Assert.IsNotNull(new DataContext("Data Source=test.db"));
            Assert.IsNotNull(new DataContext("RaisingStudio.Data.TestProject.Properties.Settings.DefaultConnectionString"));
            //Assert.IsNotNull(new DataContext("server=localhost;User Id=root;password=root;database=test;", "MySql.Data.MySqlClient"));
        }

        [TestMethod]
        public void Test3()
        {
            this.dc.Insert<Supplier>(new Supplier
            {
                Name = "for Test3",
                Status = "ok"
            });
            var query = this.dc.GetQuery<Supplier>();
            Assert.IsNotNull(query);
            var q = from s in query where s.SuppId > 0 && s.Name == "for Test3" select s;
            Assert.IsNotNull(q);
            foreach (var s in q)
            {
                Assert.IsTrue(s.SuppId > 0);
                Assert.IsTrue(s.Name == "for Test3");
                Assert.IsTrue(s.Status == "ok");
            }
        }
        
        [TestMethod]
        public void Test4()
        {
            string categoryId = Guid.NewGuid().ToString();
            this.dc.Insert<Category>(new Category
            {
                CategoryId = categoryId,
                Name = "category for Test4",
                Descn = "description for Test4"
            });
            this.dc.Insert<Product>(new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                CategoryId = categoryId,
                Name = "for Test4"                
            });
            Command command = new Command("SELECT * FROM Product WHERE CategoryId = @p1");
            command.AddParameter("@p1", categoryId);
            var q = this.dc.Query(command);
            Assert.IsNotNull(q);
            int count = 0;
            foreach (dynamic p in q)
            {
                Assert.IsNotNull(p);
                try
                {
                    Assert.AreEqual(p.CategoryId, categoryId);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                    // for ORACLE.
                    Assert.AreEqual(p.CATEGORYID, categoryId);
                }
                count++;
            }
            Assert.IsTrue(count > 0);

            q = this.dc.Query(string.Format("SELECT * FROM Category WHERE CategoryId = '{0}'", categoryId));
            Assert.IsNotNull(q);
            count = 0;
            foreach (dynamic p in q)
            {
                Assert.IsNotNull(p);
                try
                {
                    Assert.AreEqual(categoryId, p.CategoryId);
                    Assert.AreEqual("category for Test4", p.Name);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                    // for ORACLE.
                    Assert.AreEqual(categoryId, p.CATEGORYID);
                    Assert.AreEqual("category for Test4", p.NAME);                    
                }
                count++;
            }
            Assert.IsTrue(count > 0);
        }

        [TestMethod]
        public void Test5()
        {
            string categoryId = Guid.NewGuid().ToString();
            this.dc.Insert<Category>(new Category
            {
                CategoryId = categoryId,
                Name = "category for Test5",
                Descn = "description for Test5"
            });
            this.dc.Insert<Product>(new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                CategoryId = categoryId,
                Name = "for Test5"
            });
            Command command = new Command("SELECT * FROM Product WHERE CategoryId = @p1");
            command.AddParameter("@p1", categoryId);
            var q = this.dc.Query<Product>(command);
            Assert.IsNotNull(q);
            int count = 0;
            foreach (Product p in q)
            {
                Assert.IsNotNull(p);
                Assert.AreEqual(categoryId, p.CategoryId);
                Assert.AreEqual("for Test5", p.Name);
                count++;
            }
            Assert.IsTrue(count > 0);

            var qc = this.dc.Query<Category>(string.Format("SELECT * FROM Category WHERE CategoryId = '{0}'", categoryId));
            Assert.IsNotNull(qc);
            count = 0;
            foreach (Category p in qc)
            {
                Assert.IsNotNull(p);
                Assert.AreEqual(categoryId, p.CategoryId);
                Assert.AreEqual("description for Test5", p.Descn);
                count++;
            }
            Assert.IsTrue(count > 0);
        }

        [TestMethod]
        public void Test6()
        {
            this.dc.BeginTransaction();
            try
            {
                int result = this.dc.Insert<Supplier>(new Supplier
                {
                    Name = "s for Test6",
                    Status = "done",
                    City = "dalian"
                });
                Assert.AreEqual(1, result);
                int suppId = Convert.ToInt32(this.dc.GetIdentity<Supplier>());
                Assert.IsTrue(suppId > 0);
                result = this.dc.Delete<Supplier>(suppId);
                Assert.AreEqual(1, result);
                Category category = new Category
                {
                    CategoryId = Guid.NewGuid().ToString(),
                    Name = "c for Test6",
                    Descn = "d for Test6"
                };                
                Product product = new Product
                {
                    ProductId = Guid.NewGuid().ToString(),
                    Name = "p for Test6",
                    Descn = "d for Test6",
                    CategoryId = category.CategoryId
                };
                result = this.dc.Insert<Category>(category);
                Assert.AreEqual(1, result);
                result = this.dc.Insert<Product>(product);
                Assert.AreEqual(1, result);

                result = this.dc.Delete<Product>(product);
                Assert.AreEqual(1, result);
                result = this.dc.Delete<Category>(c => c.CategoryId == category.CategoryId);
                Assert.AreEqual(1, result);

                this.dc.CommitTransaction();
            }
            catch (Exception ex)
            {
                this.dc.RollbackTransaction();
                throw ex;
            }
        }

        [TestMethod]
        public void Test7()
        {
            Category category = new Category
            {
                CategoryId = Guid.NewGuid().ToString(),
                Name = "category for Test7"
            };
            Product product = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "product for Test7",
                CategoryId = category.CategoryId
            };
            Item item = new Item
            {
                ItemId = Guid.NewGuid().ToString(),
                Name = "item for Test7",
                ListPrice = 10.20M,
                ProductId = product.ProductId,
                Status = "stable"
            };
            int result = this.dc.Insert<Category>(category);
            Assert.AreEqual(1, result);
            result = this.dc.Insert<Product>(product);
            Assert.AreEqual(1, result);
            result = this.dc.Insert<Item>(item);
            Assert.AreEqual(1, result);

            item = this.dc.GetEntity<Item>(item.ItemId);
            Assert.IsNotNull(item);
            Assert.AreEqual(10.20M, item.ListPrice);
            Assert.AreEqual("item for Test7", item.Name);
            Assert.AreEqual("stable", item.Status);

            item.ListPrice = 20.30M;
            item.UnitCost = 23.45M;
            result = this.dc.Update<Item>(item);
            Assert.AreEqual(1, result);
            
            item = this.dc.GetEntity<Item>(item.ItemId);
            Assert.IsNotNull(item);
            Assert.AreEqual(20.30M, item.ListPrice);
            Assert.AreEqual(23.45M, item.UnitCost);
            Assert.AreEqual("item for Test7", item.Name);
            Assert.AreEqual("stable", item.Status);

            result = this.dc.Delete<Item>(item);
            result += this.dc.Delete<Product>(product);
            result += this.dc.Delete<Category>(category);
            Assert.AreEqual(3, result);
        }

        [TestMethod]
        public void Test8()
        {
            Category category = new Category
            {
                CategoryId = Guid.NewGuid().ToString(),
                Name = "category for Test8"
            };
            Product product = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "product for Test8",
                CategoryId = category.CategoryId
            };
            Item item = new Item
            {
                ItemId = Guid.NewGuid().ToString(),
                Name = "item for Test8",
                ListPrice = 10.20M,
                ProductId = product.ProductId,
                Status = "stable"
            };
            int result = this.dc.Insert<Category>(category);
            result += this.dc.Insert<Product>(product);
            result += this.dc.Insert<Item>(item);
            Assert.AreEqual(3, result);

            var qi = this.dc.Query<Item>(i => i.Name == item.Name && i.Status == item.Status);
            Assert.IsNotNull(qi);
            int count = 0;
            foreach (var i in qi)
            {
                Assert.AreEqual(item.Name, i.Name);
                Assert.AreEqual(item.Status, i.Status);
                count++;
            }
            Assert.IsTrue(count > 0);

            qi = this.dc.Query<Item>(new[] { "ListPrice", "Status" }, i => i.ListPrice == 10.20M || i.Status == item.Status);
            Assert.IsNotNull(qi);
            count = 0;
            foreach (var i in qi)
            {
                Assert.IsTrue(10.20M == i.ListPrice || item.Status == i.Status);
                Assert.IsNull(i.ItemId);
                Assert.IsNull(i.Name);
                count++;
            }
            Assert.IsTrue(count > 0);
        }

        [TestMethod]
        public void Test9()
        {
            Category category = new Category
            {
                CategoryId = Guid.NewGuid().ToString(),
                Name = "category for Test9"
            };
            Product product = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "product for Test9",
                CategoryId = category.CategoryId
            };
            Item item = new Item
            {
                ItemId = Guid.NewGuid().ToString(),
                Name = "item for Test9",
                ListPrice = 10.20M,
                ProductId = product.ProductId,
                Status = "stable"
            };
            int result = this.dc.Insert<Category>(category);
            result += this.dc.Insert<Product>(product);
            result += this.dc.Insert<Item>(item);
            Assert.AreEqual(3, result);

            item.ListPrice = 345.6M;
            item.Name = "for Test9";
            item.Status = "done";
            result = this.dc.Update<Item>(item, new string[] { "ListPrice" });
            Assert.AreEqual(1, result);

            item = this.dc.GetEntity<Item>(item.ItemId);
            Assert.IsNotNull(item);
            Assert.AreEqual(345.6M, item.ListPrice);
            Assert.AreEqual("item for Test9", item.Name);
            Assert.AreEqual("stable", item.Status);

            item.ListPrice = 456.7M;
            item.Name = "Test9";
            item.Status = "go";
            result = this.dc.Update<Item>(item, new string[] { "ListPrice", "Status" }, i => i.ItemId == item.ItemId && i.ListPrice == 345.6M);
            Assert.AreEqual(1, result);

            item = this.dc.GetEntity<Item>(item.ItemId);
            Assert.IsNotNull(item);
            Assert.AreEqual(456.7M, item.ListPrice);
            Assert.AreEqual("item for Test9", item.Name);
            Assert.AreEqual("go", item.Status);
        }

        [TestMethod]
        public void Test10()
        {
            Category category = new Category
            {
                CategoryId = Guid.NewGuid().ToString(),
                Name = "category for Test10"
            };
            Product product = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "product for Test10",
                CategoryId = category.CategoryId
            };
            Item item = new Item
            {
                ItemId = Guid.NewGuid().ToString(),
                Name = "item for Test10",
                ListPrice = 10.20M,
                ProductId = product.ProductId,
                Status = "stable",
                UnitCost = 1234.5M
            };
            int result = this.dc.Insert<Category>(category);
            result += this.dc.Insert<Product>(product);
            result += this.dc.Insert<Item>(item, new Expression<Func<Item, object>>[] 
            { 
                i => i.ItemId,
                i => i.Name,
                i => i.ListPrice,
                i => i.ProductId,
                i => i.Status
            });
            Assert.AreEqual(3, result);

            item = this.dc.GetEntity<Item>(item.ItemId);
            Assert.IsNotNull(item);
            Assert.AreEqual(10.20M, item.ListPrice);
            Assert.AreEqual("item for Test10", item.Name);
            Assert.AreEqual("stable", item.Status);
            Assert.AreEqual(null, item.UnitCost);

            int itemCount = this.dc.GetCount<Item>(i => i.ItemId == item.ItemId);
            long itemLongCount = this.dc.GetCount<Item>();
            Assert.IsTrue(itemCount > 0);
            Assert.IsTrue(itemLongCount > 0);
            Assert.IsTrue(itemCount <= itemLongCount);

            item = new Item
            {
                ItemId = Guid.NewGuid().ToString(),
                Name = "another Item for Test10",
                ListPrice = 123456.78M,
                ProductId = product.ProductId,
                Status = "stable",
                UnitCost = 54321.1M
            };
            result = this.dc.Insert<Item>(item);
            Assert.AreEqual(1, result);

            decimal min = Convert.ToDecimal(this.dc.GetMin<Item>(t => t.ListPrice));
            decimal max = Convert.ToDecimal(this.dc.GetMax<Item>(t => t.ListPrice));
            Assert.IsTrue(max > min);

            decimal avg = 0.0M;
            try
            {
                avg = Convert.ToDecimal(this.dc.GetAvg<Item>(t => t.ListPrice));
     
                Assert.IsTrue(max > avg);
                Assert.IsTrue(min < avg);
            }
            catch (OverflowException ex)
            {
                Console.WriteLine(ex);
                // for ORACLE, it seems this is a bug of "Oracle.DataAccess", because there is no problem with the SQL:
                // SELECT AVG(ListPrice) FROM Item
            }
            decimal sum = Convert.ToDecimal(this.dc.GetSum<Item>(t => t.ListPrice));
            Assert.IsTrue(sum > max);
        }

        [TestMethod]
        public void Test11()
        {
            Category category = new Category
            {
                CategoryId = Guid.NewGuid().ToString(),
                Name = "category for Test11"
            };
            Product product = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "product for Test11",
                CategoryId = category.CategoryId
            };
            Item item = new Item
            {
                ItemId = Guid.NewGuid().ToString(),
                Name = "item for Test11",
                ListPrice = 10.20M,
                ProductId = product.ProductId,
                Status = "stable",
                UnitCost = 1234.5M
            };
            int result = this.dc.Save<Category>(category);
            result += this.dc.Save<Product>(product);
            result += this.dc.Save<Item>(item, new Expression<Func<Item, object>>[] 
            { 
                i => i.ItemId,
                i => i.Name,
                i => i.ListPrice,
                i => i.ProductId,
                i => i.Status
            });
            Assert.AreEqual(3, result);

            Assert.IsTrue(this.dc.Exists<Item>(item.ItemId));
            Assert.IsTrue(this.dc.Exists<Product>(p => p.Name == product.Name));

            product.Name = "another product for Test11";
            result = this.dc.Save<Product>(product);
            Assert.AreEqual(1, result);

            product = this.dc.GetEntity<Product>(product.ProductId);
            Assert.IsNotNull(product);
            Assert.AreEqual("another product for Test11", product.Name);

            result = this.dc.Save<Item>(item, new string[] { "UnitCost" });
            Assert.AreEqual(1, result);

            decimal unitCost = Convert.ToDecimal(this.dc.EntityScalar<Item>(new Command("SELECT [UnitCost] FROM [Item] WHERE [ItemId] = @p1", new[] { "@p1" }, new[] { item.ItemId })));
            Assert.AreEqual(item.UnitCost, unitCost);
        }

        [TestMethod]
        public void Test12()
        {
            // ordering
            var q = from i in this.dc.GetQuery<Item>()
                    orderby i.ListPrice
                    select i;
            Assert.IsNotNull(q);
            int count = 0;
            decimal value =0.0M;
            foreach (var i in q)
            {
                Assert.IsTrue(i.ListPrice >= value);
                value = i.ListPrice;
                count++;
            }
            Assert.IsTrue(count > 0);

            var q2 = this.dc.Query<Item>(ExpressionExtension.Empty<Item>().OrderByDescending<Item>(i => i.ListPrice).OrderBy("UnitCost"));
            Assert.IsNotNull(q2);
            value = decimal.MaxValue;
            foreach (var i in q2)
            {
                Assert.IsTrue(i.ListPrice <= value);
                value = i.ListPrice;
                count++;
            }
            Assert.IsTrue(count > 0);
        }

        [TestMethod]
        public void Test13()
        {
            // paging
            List<Item> items = this.dc.Query<Item>(ExpressionExtension.Empty<Item>().Take(3)).ToList();
            Assert.IsNotNull(items);
            Assert.AreEqual(3, items.Count);

            var q = (from i in this.dc.GetQuery<Item>()
                    select i).Skip(1).Take(2);
            int index = 1;
            foreach (var i in q)
            {
                Assert.AreEqual(items[index++].ItemId, i.ItemId);
            }
            Assert.AreEqual(3, index);

            int count = this.dc.Query<Item>(ExpressionExtension.Empty<Item>().Skip(1)).Count();
            Assert.AreEqual(this.dc.GetCount<Item>() - 1, count);
        }

        [TestMethod]
        public void Test14()
        {
            // convert
            Category category = new Category
            {
                CategoryId = Guid.NewGuid().ToString(),
                Name = "category for Test11"
            };
            Product product = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "product for Test11",
                CategoryId = category.CategoryId
            };
            TestItem item = new TestItem
            {
                ItemId = Guid.NewGuid().ToString(),
                Name = "item for Test14",
                ListPrice = 123.4f,
                UnitCost = 567.8d,
                Status = ItemStatus.none,
                ProductId = product.ProductId
            };
            int result = this.dc.Insert<Category>(category);
            result += this.dc.Insert<Product>(product);
            result += this.dc.Insert<TestItem>(item);
            Assert.AreEqual(3, result);

            item = this.dc.GetEntity<TestItem>(item.ItemId);
            Assert.IsNotNull(item);
            Assert.AreEqual(ItemStatus.none, item.Status);
            Assert.AreEqual(123.4f, item.ListPrice);
            Assert.AreEqual(567.8d, item.UnitCost);

            foreach (var i in this.dc.Query<TestItem>())
            {
                Assert.IsNotNull(i);
                Assert.IsTrue(i.Status == ItemStatus.none || i.Status == ItemStatus.stable || i.Status == ItemStatus.go);
            }
        }

        [TestMethod]
        public void Test15()
        {
            // mapping
            Category category = new Category
             {
                 CategoryId = Guid.NewGuid().ToString(),
                 Name = "category for Test15"
             };
            Product product = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "product for Test15",
                CategoryId = category.CategoryId
            };
            TItem item = new TItem
            {
                CItemId = Guid.NewGuid().ToString(),
                CName = "item for Test15",
                CListPrice = 10.20M,
                CProductId = product.ProductId,
                CStatus = "stable",
                CUnitCost = 1234.5M
            };
            int result = this.dc.Save<Category>(category);
            result += this.dc.Save<Product>(product);
            result += this.dc.Save<TItem>(item);
            Assert.AreEqual(3, result);

            item.CName = "name for Test15";
            item.CListPrice = 20.10M;
            result = this.dc.Save<TItem>(item);
            Assert.AreEqual(1, result);

            var item2 = this.dc.Query<Item>(t => t.ItemId == item.CItemId).ToArray()[0];
            item = this.dc.GetEntity<TItem>(item.CItemId);            
            Assert.AreEqual(item.CItemId, item2.ItemId);
            Assert.AreEqual(item.CName, item2.Name);

            result = this.dc.Delete<TItem>(t => t.CItemId == item.CItemId);
            Assert.AreEqual(1, result);
        }

        [TestMethod]
        public void PerformanceTest()
        {
            this.dc.Log = null;

            Category category = new Category
            {
                CategoryId = Guid.NewGuid().ToString(),
                Name = "category for Test11"
            };
            Product product = new Product
            {
                ProductId = Guid.NewGuid().ToString(),
                Name = "product for Test11",
                CategoryId = category.CategoryId
            };
            
            List<Item> items = new List<Item>();
            int count = 100;
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < count; i++)
            {
                Item item = new Item
                {
                    ItemId = Guid.NewGuid().ToString(),
                    Name = "item for PerformanceTest",
                    ListPrice = 123.4M,
                    UnitCost = 567.8M,
                    Status = "none",
                    ProductId = product.ProductId
                };
                items.Add(item);
            }
            sw.Stop();
            long createTime = sw.ElapsedMilliseconds;
            
            sw.Restart();
            foreach (var item in items)
            {
                this.dc.Insert<Item>(item);
            }
            sw.Stop();
            long insertTime = sw.ElapsedMilliseconds;

            sw.Restart();
            List<Item> itemList = this.dc.Query<Item>().ToList();
            sw.Stop();
            long queryTime = sw.ElapsedMilliseconds;

            List<Item> itemList2 = new List<Item>();
            IDbCommand command = this.dc.Connection.CreateCommand();
            command.CommandText = "SELECT * FROM Item";
            this.dc.Connection.Open();
            IDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection);
            sw.Restart();
            while (reader.Read())
            {
                Item item = new Item();
                item.ItemId = Convert.ToString(reader["ItemId"]);
                item.Name = Convert.ToString(reader["Name"]);
                item.ListPrice = Convert.ToDecimal(reader["ListPrice"]);
                item.UnitCost = reader.IsDBNull(reader.GetOrdinal("UnitCost")) ? (decimal?)null : Convert.ToDecimal(reader["UnitCost"]);                    
                item.Status = Convert.ToString(reader["Status"]);
                item.ProductId = Convert.ToString(reader["ProductId"]);
                item.Image = Convert.ToString(reader["Image"]);
                item.Supplier = reader.IsDBNull(reader.GetOrdinal("Supplier")) ? (int?)null : Convert.ToInt32(reader["Supplier"]);
                itemList2.Add(item);
            }
            sw.Stop();
            reader.Close();
            long readTime = sw.ElapsedMilliseconds;

            sw.Restart();
            foreach (var item in items)
            {
                item.Status = "done";
                item.ListPrice = 89.32M;
            }
            sw.Stop();
            long changeTime = sw.ElapsedMilliseconds;

            sw.Restart();
            foreach (var item in items)
            {
                this.dc.Update<Item>(item);
            }
            sw.Stop();
            long updateTime = sw.ElapsedMilliseconds;

            sw.Restart();
            foreach (var item in items)
            {
                this.dc.Delete<Item>(item);
            }
            sw.Stop();
            long deleteTime = sw.ElapsedMilliseconds;

            sw.Restart();
            foreach (var item in itemList)
            {
                int index = items.FindIndex((i) => i.ItemId == item.ItemId);
                if (index >= 0)
                {
                    items.RemoveAt(index);
                }
            }
            sw.Stop();
            long removeTime = sw.ElapsedMilliseconds;

            // mssql:
            // count: [100], create: 0, insert: 879, change: 0, update: 965, remove: 0, delete: 785
            // count: [1000], create: 1, insert: 7831, change: 0, update: 9122, remove: 28, delete: 7186

            // mysql:
            // count: [100], create: 0, insert: 2186, change: 0, update: 2549, remove: 1, delete: 2239
            // count: [1000], create: 10, insert: 24715, change: 0, update: 30128, remove: 27, delete: 25250
			// (linux+mono)count: [100], create: 0, insert: 194, change: 0, update: 324, remove: 1, delete: 158


            // sqlite:
            // count: [100], create: 0, insert: 8853, change: 0, update: 8763, remove: 0, delete: 9495

            // oracle:
            // count: [100], create: 0, insert: 317, change: 0, update: 450, remove: 0, delete: 257
            // count: [1000], create: 1, insert: 2796, change: 0, update: 4323, remove: 6, delete: 2521

            Console.WriteLine("count: [{0}], create: {1}, insert: {2}, change: {3}, update: {4}, remove: {5}, delete: {6}", count, createTime, insertTime, changeTime, updateTime, removeTime, deleteTime);

            Assert.IsTrue(insertTime > createTime);
            Assert.IsTrue(updateTime > changeTime);
            Assert.IsTrue(deleteTime > removeTime);

            Assert.AreEqual(itemList.Count, itemList2.Count);

            // mssql:
            // count: [1000], read: 12, query: 14

            // mysql:
            // count: [1000], read: 13, query: 16
			// (linux+mono)count: [100], read: 2, query: 10

            // oracle:
            // count: [100], read: 11, query: 6
            // count: [1000], read: 33, query: 12

            Console.WriteLine("count: [{0}], read: {1}, query: {2}", count, readTime, queryTime);

            Assert.IsTrue((readTime < 100 && queryTime < 100) || ((queryTime > 100) && (queryTime < (readTime * 1.2))));
        }
    }
}
